//  IDVI 1.0 source copyright 1996 Garth A. Dickie
//
//  This source is free for non-commercial use.  No warranty, etc.
//  Please acknowledge reuse by including the line:
//
//  "Based in part on IDVI 1.0 source copyright 1996 Garth A. Dickie"
//
//  in your documentation and source code.  For commercial use or
//  distribution, please contact the author.  Please also send
//  questions, comments, bug reports, or fixes.
//
//  Best Regards,
//  Garth A. Dickie
//  dickie@elastic.avid.com

package ibook.v10.idvi.display;

import java.awt.Graphics;

abstract class View {
    //  setParent( ) is used by Views which contain other Views, to tell their
    //  children how to notify their parent of changes in expansion and bounds.
    //
    //  setParent( ), getFlags( ), and getBounds( ) should be called in that order.

    void setParent( View parent, int indexInParent ) {
    }

    //  getFlags( ) is used by a parent to find out how much information the
    //  child will need from the parent later.  The flags are:
    //
    //      kFlagHasComponents:
    //          The child contains at least one Component (such as an Applet),
    //          and therefore needs special treatment when its offset changes
    //          or it is hidden from view.
    //
    //      kFlagGetsMouseEvents:
    //          The child is interested in tracking the mouse.  This is used
    //          by ActionViews, for example, but *not* for Applets, because
    //          they will already get mouse events through the Component heierarchy.

    final static int    kFlagHasComponents   = 1;
    final static int    kFlagGetsMouseEvents = 2;

    int getFlags( ) {
        return 0;
    }

    //  getBounds( ) should calculate the bounds of the given view.  The scale, x, y,
    //  and block parameters are used by the flyweight classes, such as RuleView and
    //  CharacterView.
    //
    //  The x and y parameters have *not* been scaled by the scale factor.  The
    //  appropriate scaling method is ( x + scale - 1 ) / scale, with the assumption
    //  that negative x and y are very uncommon so we don't worry about the glitch
    //  at zero.
    //
    //  The bounds parameter has undefined contents; it is used to return the bounds
    //  of the View to the caller.  The bounds rectangle which is returned should be
    //  the un-expanded bounds rectangle; the expansion value for this view is returned
    //  as the result.
    //
    //  NOTE: setParent( ) must be called before getBounds( ).  (This is required by
    //        the ToggleView class, which needs to ask its parent for the position of
    //        the previous child in order to compute its expansion.)
    //
    //  NOTE: getBounds( ) *must* be called during initialization.

    int getBounds( DVIRectangle bounds, int scale, int x, int y, Block block ) {
        bounds.set( );
        return 0;
    }

    //  showComponents( ) and hideComponents( ) are called only if the kFlagHasComponents
    //  flag was set in the result of getFlags( ).  showComponents( ) is called immediately
    //  after getBounds( ) in the initialization process, after childChangedFlags( ) if the
    //  child sets the kFlagHasComponents flag, whenever the offset of this View is changed,
    //  and whenever this View becomes visible because a ToggleView has been made visible.
    //  hideComponents( ) is called whenever this View becomes invisible because a ToggleView
    //  has been made invisible.
    //  
    //  The componentYOffset parameter of showComponents( ) may not be the same as the offset
    //  passed to paint( ).

    void showComponents( int componentXOffset, int componentYOffset ) {
    }

    void hideComponents( ) {
    }

    //  The main method of a view is paint( ).  The color parameter is a color index,
    //  to be used with the ScaledColorModel.getColor( ) and getColorModel( ) methods.
    //  The bounds rectangle is the original DVI bounds rectangle, and already has the
    //  yOffset and any expansion applied to it.  The clip rectangle is in screen
    //  coordinates, and may be compared directly with the bounds rectangle.  However,
    //  it is expected that the caller has already checked clipping for this View.
    //
    //  The contents of the bounds parameter may be overwritten.

    void paint( Graphics g, int color, DVIRectangle bounds, DVIRectangle clip, int yOffset ) {
    }

    //  The mouse event routines are somewhat different from the usual event handlers
    //  for a Component.  All information is passed from the top down, and a Container
    //  will convert mouseMoved events into mouseEnter or mouseExit events for a child,
    //  for example.  The return value is interpreted in the same way as for the
    //  event routines of Components -- false means that the event was not consumed,
    //  true means that it was.

    void mouseEnter( int x, int y ) {
    }

    void mouseMove( int x, int y ) {
    }

    boolean mouseDown( int clickCount ) {
        return false;
    }

    void mouseDrag( int x, int y ) {
    }

    boolean mouseUp( int modifiers ) {
        return false;
    }

    void mouseExit( ) {
    }

    //  childAddedToBounds( ) is called during loading, by the most recent child
    //  of the current View, to indicate that its bounds rectangle is out of date
    //  and should be updated.  This may in turn affect the bounds of the current
    //  View, in which case this View should call the childAddedContent( ) method
    //  of its parent, etc.  It is gauranteed that the new bounds rectangle of the
    //  child contains the old bounds rectangle of the child.
    //
    //  No drawing or calls to repaint( ) should result from a call to this method.
    //  Instead, the child which initiated the chain of childAddedToBounds( ) calls
    //  the repaint( ) method of the parent ViewPanel.
    //
    //  The expansion value should be unchanged from the value already known to the
    //  parent; it is passed only because the parent usually doesn't keep the
    //  expansion value around, but needs it during this call.

    void childAddedToBounds( DVIRectangle newBounds, int expansion ) {
    }

    //  childAddedToFlags( ) is similar to childAddedToBounds( ).  It is only called
    //  during loading, by the most recent child of this View.  The new flags value
    //  is garaunteed to be a superset of the previous flags value.

    void childAddedToFlags( int newFlags ) {
    }

    //  childChangedExpansion( ) is called by any child of the current View, during
    //  or after loading, to indicate that its expansion value is out of date and
    //  should be updated by the given expansionDelta.  If expansionDelta is positive,
    //  then the new space is at yPosition.  If expansionDelta is negative, then the
    //  space from yPosition to yPosition - expansionDelta is to be removed.

    void childChangedExpansion( int childIndex, int expansionDelta, int yPosition ) {
    }

    //  childBounds( ) is used by a child to find out what its parent thinks that
    //  its bounds are.  The resulting bounds rectangle has already had the expansion
    //  of the child applied; the child should remove the expansion to find its
    //  actual original size.

    void childBounds( DVIRectangle childBounds, int childIndex ) {
    }

    //  getBottomOfPreviousChild( ) is used by a child to find out how much whitespace
    //  precedes it on the page.  It is needed by ToggleViews, to calculate extra
    //  contraction needed to make things look good when a line is removed.  If the
    //  ToggleView is the first child of a ContainerView, it will ask its parent for
    //  the answer, etc.  If the value Integer.MAX_VALUE is returned, then the caller
    //  knows that it is the first text on the page.

    int getBottomOfPreviousChild( int childIndex ) {
        return Integer.MAX_VALUE;
    }

    //  repaint( ) is called by any child of the current View, during or after loading,
    //  to indicate that it wished to have its paint( ) method called at some time
    //  in the future.  The parameter repaintBounds is the expanded, but not offset,
    //  bounds rectangle of the area to be repainted.  The childIndex is used to find
    //  the correct offset to be added to the bounds rectangle before it is passed
    //  up the heierarchy (eventually reaching a ViewPanel).  The delay is used as
    //  the delay value passed to Component.repaint( ) by the ViewPanel, and should
    //  be long during loading (.1 second?) and short during interaction (0?).

    final static long kRepaintDelayProgressive = 100;
    final static long kRepaintDelayInteraction = 0;

    void repaint( DVIRectangle repaintBounds, int childIndex, long delay ) {
    }

    //  toString( ) should return a new string containing information about this
    //  View, but not about any children.

    public String toString( ) {
        String className = getClass( ).getName( );
        int offset = className.lastIndexOf( '.' );
        return className.substring( offset + 1 );
    }

    //  printStructure( ) is called by debugging code to display the structure of
    //  the View heierarchy.  It should use toString( ) to get information on the
    //  present View, and call printStructure recursively on any children.

    void printStructure( String indent ) {
        System.out.println( indent + toString( ));
    }
}
